/**
 * 
 */
package Jeu_Himalaya;

/**
 * 
 * @author Edwin Wilson/Wang Zhan
 * @version 1.0.0
 */
public class Action {
	
	/**
	 * m_typeAction : cheminTerre, cheminGlace, cheminPierre, transaction
	 */
	private Caravanier m_caravanier;
	private String m_typeAction;
	
	// ---						Premier constructeur
	//
	/**
	 * Premier constructeur
	 * @param caravanier le numero corespondant au caravanier qui execute l'action
	 * @param typeAction le numero corespondant a l'action souhaitee
	 */
	public Action(Caravanier caravanier, String typeAction){
		m_caravanier = caravanier;
		m_typeAction = typeAction;
	}
	
	//				-----------		Accesseurs de consultation	-----------
	//
	
	//	---							Methode getCaravanier
	//
	/**
	 * Retourne la valeur de l'attribut m_caravanier 
	 * @return la valeur de m_caravanier
	 */
	public Caravanier getCaravanier(){
		return m_caravanier;
	}
	
	//	---							Methode getTypeAction
	//
	/**
	 * Retourne la valeur de l'attribut m_typeAction
	 * @return la valeur de m_typeAction
	 */
	public String getTypeAction(){
		return m_typeAction;
	}
	
	//				------------	Methodes heritees de object	------------
	//
	
	//	---							Surcharge de la methode equals
	//
	/**
	 * Indique si l'objet Action support est egal a l'objet Action cible
	 * @param op2
	 * @return vrai si Action support est egal a Action cible, sinon faux
	 */
	public boolean equals(Action op2){
		if(m_caravanier.equals(op2.m_caravanier) && m_typeAction == op2.m_typeAction) return true;
		return false;
	}
	
	//	---							Surcharge de la methode clone
	//
	/**
	 * Surcharge de la methode clone
	 * @return Action clone de l'objet Action support
	 */
	public Action clone(){
		Action resultat = new Action(m_caravanier, m_typeAction);
		return resultat;
	}
	
	//				-------------	Aide aux tests unitaires	------------
	//
	
	//	---							Methode toString
	//
	/**
	 * Retourne l'Action sous forme de chaine caracteres de la forme
	 * ( int caravanier, int typeAction)
	 */
	public String toString(){
		String resultat = "(" + m_caravanier.toString() + ", " + m_typeAction + ")";
		return resultat;
	}
	
	//				-------------	Methode de la classe	--------------
	//
	
	//	---							Methode collecterRessource
	//
	//	Cette methode ajoute a l'attribut ressource du Caravanier la
	//	ressource de plus faible valeur contenue dans l'attribut
	//	ressources de l'objet Village ou se situe le Caravanier
	/**
	 * Ajoute aux ressource du caravanier la ressource de plus faible valeur contenue dans le village
	 * ou il se trouve.
	 * @throws Throwable
	 */
	public boolean collecterRessource(){
		
		int numVillage = m_caravanier.getPosition().numero;
		Village villageActuel = m_caravanier.getPosition();
		
		//	S'il n'y a pas de ressources dans le village on renvoie false
		if (villageActuel.getRessource().isEmpty() == true) return false;
		
		// On recherche la ressource de plus faible valeur
		int i, nbRessourcesDiminue, nbRessourcesAugmente;
		villageActuel.getRessource();
		String ressourceACollecter;
		
		// On prend la ressource de plus petite valeur
		for(i=0;i<tabRessources.length;i++){
			if (villageActuel.getRessource().get(tabRessources[i]) != 0){
				ressourceACollecter = tabRessources[i];
				break;
			}
		}
		
		// On diminue le nombre de ressources du type a collecter dans le village
		nbRessourcesDiminue = villageActuel.getRessource().get(ressourceACollecter)-1;
		villageActuel.getRessource().remove(ressourceACollecter);
		villageActuel.getRessource().put(ressourceACollecter, nbRessourcesDiminue);
		
		// On augmente le nombre de ressources du type a collecter chez le caravanier
		nbRessourcesAugmente = (int)m_caravanier.getRessources().get(ressourceACollecter)+1;
		m_caravanier.getRessources().remove(ressourceACollecter);
		m_caravanier.getRessources().put(ressourceACollecter, nbRessourcesAugmente);
		return true;
		
	}
	
	/**
	 * Honore la commande d'un village, les ressources necessaires sont retir&eacute;es au caravanier
	 * et ajoutées au village. La commande n'est ensuite plus disponnible au village.
	 * @throws Throwable
	 */
	//	---							Methode honorerCommande
	//
	//	Programme avec List afin de respecter la conception mais ne gere pas le cas 
	//	ou la commande necessite plus d'une ressource du meme type
	//	cette methode est destinee a etre utilisee dans les autres methodes de Action
	//
	private boolean honorerCommande() {
		Village villageActuel = m_caravanier.getPosition();
		int i;
		//	Traiter le cas ou le caravanier ne possede pas toutes les ressources necessaires
		//
		for(i=0; i<villageActuel.commande.getRessourceNecessaire().size(); i++){
			if(m_caravanier.getRessources().get(villageActuel.commande.ressourcesNecessaires.get(i).nom) == 0) return false;		
		}
		//	Cas general : prendre des ressources au caravanier; ajouter les ressources a la banque;
		//
		int j = 0;
		for(i=0; i<villageActuel.commande.getRessourceNecessaire().size(); i++){
			//	Sauver le nombre de ressources actuelles
			//
			j = m_caravanier.getRessources().get(villageActuel.getCommande().getRessourceNecessaire().get(i).nom);
			//	Retirer les ressources du HashMap ressources
			//
			m_caravanier.getRessources().remove(villageActuel.getCommande().getRessourceNecessaire().get(i).nom);
			//	Replacer la ressource avec une valeur diminuee
			//
			m_caravanier.getRessources().put(villageActuel.getCommande().getRessourceNecessaire().get(i).nom, j - 1);
			//	Ajouter la ressource retiree au caravanier dans la banque, meme procede que pour le caravanier avec une 
			//	Valeur augmentee
			//
			j = Himalaya.getBanque().sacRessources.get(villageActuel.getCommande().getRessourceNecessaire().get(i).nom);
			Hiamalaya.getBanque().sacRessources.remove(villageActuel.getCommande().getRessourceNecessaire().get(i).nom);
			Himalaya.getBanque().sacRessources.put(villageActuel.getCommande().getRessourceNecessaire().get(i).nom, j+1);
		}
		//	Placer la commande dans le sac
		//	Meme procede que pour banque et caravanier avec une valeur augmentee
		//
		j = Banque.sacCommandes.get(villageActuel.commande.valeurCommande);
		Banque.sacCommandes.remove(villageActuel.commande.valeurCommande);
		Banque.sacCommandes.put(villageActuel.commande.valeurCommande, j+1);
		villageActuel.commande = null;
		
		
	}
	
	/**
	 * Honore une commande, r&eacute;alise le troc, dépose un stupa sur le village.
	 * @return true si l'op&eacute;ration est reussie.
	 */
	//	---							Methode trocStupa
	//
	//	Cette methode honore une commande, realise le troc et depose un stupa
	public boolean trocStupa(){
		
		//	Honorer la commande
		//
		honorerCommande();
		///	---							Partie troc
		//
		//	On ajoute la valeur de la commande au pouvoir economique du caravanier
		int ancienPouvoirEco = m_caravanier.getPouvoirEconomique();
		m_caravanier.setPouvoirEconomique(ancienPouvoirEco + m_caravanier.getPosition().getCommande().getValeurCommande());
		//	On ajoute la commande a la banque et on la retire au village
		//
		Himalaya.getBanque().sacCommandes.put(m_caravanier.getVillage().getCommande());
		m_caravanier.getVillage().setCommande(null);
		
		//	---							Partie Stupa
		//
		//	On pose un stupa sur le village, s'il y'en a deja un on le remplace par le nouveau
		m_caravanier.getVillage().setStupa(m_caravanier.couleur);
		return true;
	}
	
	//	---									Methode delegationStupa
	//
	//	Cette serie de methodes envoie des delegations dans les regions passees en parametre, pose un stupa
	//	le village du caravanier.
	//
	/**
	 * Pose un stupa et envoie une delegation dans une region passee en parametre
	 * @param r
	 * @return true si tout se passe bien, false si le nombre delegations est insuffisant ou si le village
	 * n'est pas adjacent a la region
	 */
	public boolean delegationStupa(Region r){
			//	Honorer la commande
			//
			honorerCommande();
			//	---							Partie stupa
			//
			//	On pose un stupa sur le village, s'il y'en a deja un on le remplace par le nouveau
			m_caravanier.getVillage().setStupa(m_caravanier.couleur);
			return true;
			//	---							Partie delegation
			//
			//	On verifie que le village appartient a la region demandee
			//
			int i;
			boolean appartientVillage = false;
			for(i = 0; i<r.getVillages.size(); i++){
				if (m_caravanier.getVillage().equals(r.getVillages().get(i))){
					appartientVillage = true;
					break;
				}
			}
			//	On verifie que le nombre de delegations restantes est suffisant
			//
			if(appartientVillage == true){
				if (m_caravanier.nbDelegationsRestantes == 0) return false;
			}
			else return false;
			//	On envoie les delegations dans les regions saouhaitees
			//
			int nbDeleg = r.getNbDelegation(m_caravanier.couleur), nbDelegCarav = m_caravanier.getNbDelegationsRestantes();
			r.getNbDelegation.remove(m_caravanier.couleur);
			r.getNbDelegation.put(m_caravanier.couleur,nbDeleg+1);
			m_caravanier.setNbDelegationsRestantes(nbDelegCarav-1);
			return true;
	}
	
	//	---	Methode delegationStupa avec deux regions
	//
	/**
	 * Pose un stupa et envoie des delegations dans les regions passees en parametre
	 * @param r1
	 * @param r2
	 * @return true si tout se passe bien, false si le nombre delegations est insuffisant ou si le village
	 * n'est pas adjacent a unes des regions
	 */
	public boolean delegationStupa(Region r1, Region r2){
				//		Honorer la commande
				//
				honorerCommande();
				//	---							Partie stupa
				//
				//	On pose un stupa sur le village, s'il y'en a deja un on le remplace par le nouveau
				m_caravanier.getVillage().setStupa(m_caravanier.couleur);
				return true;
				//	---							Partie delegation
				//
				//	On verifie que le village appartient a la region demandee
				//
				int i;
				boolean appartientVillage = false;
				for(i = 0; i<r1.getVillages.size(); i++){
					if (m_caravanier.getVillage().equals(r.getVillages().get(i))){
						appartientVillage = true;
						break;
					}
				}
				
				appartientVillage = false;
				for(i = 0; i<r2.getVillages.size(); i++){
					if (m_caravanier.getVillage().equals(r.getVillages().get(i))){
						appartientVillage = true;
						break;
					}
				}
				//	On verifie que le nombre de delegations restantes est suffisant
				//
				if(appartientVillage == true){
					if (m_caravanier.nbDelegationsRestantes < 2) return false;
				}
				else return false;
				//	On envoie les delegations dans les regions saouhaitees et on les retire au caravanier
				//
				int nbDeleg = r.getNbDelegation(m_caravanier.couleur), nbDelegCarav = m_caravanier.getNbDelegationsRestantes();
				r.getNbDelegation.remove(m_caravanier.couleur);
				r.getNbDelegation.put(m_caravanier.couleur,nbDeleg+1);
				m_caravanier.setNbDelegationsRestantes(nbDelegCarav-1);
				nbDelegCarav = m_caravanier.getNbDelegationsRestantes();
				r2.getNbDelegation.remove(m_caravanier.couleur);
				r2.getNbDelegation.put(m_caravanier.couleur,nbDeleg+1);
				m_caravanier.setNbDelegationsRestantes(nbDelegCarav-1);
				return true;
		}

	//	---	Methode delegationStupa avec 3 regions
	//
	
	/**
	 * 
	 * Pose un stupa et envoie des delegations dans les regions passees en parametre
	 * @param r1
	 * @param r2
	 * @param r3
	 * @return true si tout se passe bien, false si le nombre delegations est insuffisant ou si le village
	 * n'est pas adjacent a la region
	 */
	public boolean delegationStupa(Region r1, Region r2, Region r3){
				//		Honorer la commande
				//
				honorerCommande();
				//	---							Partie stupa
				//
				//	On pose un stupa sur le village, s'il y'en a deja un on le remplace par le nouveau
				m_caravanier.getVillage().setStupa(m_caravanier.couleur);
				return true;
				//	---							Partie delegation
				//
				//	On verifie que le village appartient a la region demandee
				//
				int i;
				boolean appartientVillage = false;
				for(i = 0; i<r1.getVillages.size(); i++){
					if (m_caravanier.getVillage().equals(r.getVillages().get(i))){
						appartientVillage = true;
						break;
					}
				}
				
				appartientVillage = false;
				for(i = 0; i<r2.getVillages.size(); i++){
					if (m_caravanier.getVillage().equals(r.getVillages().get(i))){
						appartientVillage = true;
						break;
					}
				}
				
				appartientVillage = false;
				for(i = 0; i<r3.getVillages.size(); i++){
					if (m_caravanier.getVillage().equals(r.getVillages().get(i))){
						appartientVillage = true;
						break;
					}
				}
				//	On verifie que le nombre de delegations restantes est suffisant
				//
				if(appartientVillage == true){
					if (m_caravanier.nbDelegationsRestantes < 3) return false;
				}
				else return false;
				//	On envoie les delegations dans les regions saouhaitees et on les retire au caravanier
				//
				int nbDeleg = r.getNbDelegation(m_caravanier.couleur), nbDelegCarav = m_caravanier.getNbDelegationsRestantes();
				r.getNbDelegation.remove(m_caravanier.couleur);
				r.getNbDelegation.put(m_caravanier.couleur,nbDeleg+1);
				m_caravanier.setNbDelegationsRestantes(nbDelegCarav-1);
				nbDelegCarav = m_caravanier.getNbDelegationsRestantes();
				r2.getNbDelegation.remove(m_caravanier.couleur);
				r2.getNbDelegation.put(m_caravanier.couleur,nbDeleg+1);
				m_caravanier.setNbDelegationsRestantes(nbDelegCarav-1);
				nbDelegCarav = m_caravanier.getNbDelegationsRestantes();
				r3.getNbDelegation.remove(m_caravanier.couleur);
				r3.getNbDelegation.put(m_caravanier.couleur,nbDeleg+1);
				m_caravanier.setNbDelegationsRestantes(nbDelegCarav-1);
				return true;
	}
	
	
	//	---							Methode delegationTroc
	//
	//	Cette serie de methodes envoie des delegations dans les regions passees en parametre, pose un stupa
	//	le village du caravanier.
	//
	/**
	 * Realise un troc et envoie une delegation dans une region passee en parametre
	 * @param r 
	 * @return true si tout se passe bien, false si le nombre delegations est insuffisant ou si le village
	 * n'est pas adjacent a la region
	 */
	public boolean delegationTroc(Region r){
		//	Honorer la commande
		//
		honorerCommande();
		//	Partie troc
		//
		//		On ajoute la valeur de la commande au pouvoir economique du caravanier
		int ancienPouvoirEco = m_caravanier.getPouvoirEconomique();
		m_caravanier.setPouvoirEconomique(ancienPouvoirEco + m_caravanier.getPosition().getCommande().getValeurCommande());
		//	On ajoute la commande a la banque et on la retire au village
		//
		Himalaya.getBanque().sacCommandes.put(m_caravanier.getVillage().getCommande());
		m_caravanier.getVillage().setCommande(null);
		//				Partie delegation
		//
		//		On verifie que le village appartient a la region demandee
		//
		int i;
		boolean appartientVillage = false;
		for(i = 0; i<r.getVillages.size(); i++){
			if (m_caravanier.getVilsrclage().equals(r.getVillages().get(i))){
				appartientVillage = true;
				break;
			}
		}
		//	On verifie que le nombre de delegations restantes est suffisant
		//
		if(appartientVillage == true){
			if (m_caravanier.nbDelegationsRestantes == 0) return false;
		}
		else return false;
		//	On envoie les delegations dans les regions saouhaitees
		//
		int nbDeleg = r.getNbDelegation(m_caravanier.couleur), nbDelegCarav = m_caravanier.getNbDelegationsRestantes();
		r.getNbDelegation.remove(m_caravanier.couleur);
		r.getNbDelegation.put(m_caravanier.couleur,nbDeleg+1);
		m_caravanier.setNbDelegationsRestantes(nbDelegCarav-1);
		return true;
	}
	
	//	---		Methode delegationTroc avec 2 regions
	//
	/**
	 * Pose un stupa et envoie des delegations dans les regions passees en parametre
	 * @param r1
	 * @param r2
	 * @return true si tout se passe bien, false si le nombre delegations est insuffisant ou si le village
	 * n'est pas adjacent a la region
	 */
	public boolean delegationTroc(Region r1, Region r2){
		//		Honorer la commande
		//
		honorerCommande();
		//	Partie troc
		//
		//		On ajoute la valeur de la commande au pouvoir economique du caravanier
		int ancienPouvoirEco = m_caravanier.getPouvoirEconomique();
		m_caravanier.setPouvoirEconomique(ancienPouvoirEco + m_caravanier.getPosition().getCommande().getValeurCommande());
		//	On ajoute la commande a la banque et on la retire au village
		//
		Himalaya.getBanque().sacCommandes.put(m_caravanier.getVillage().getCommande());
		m_caravanier.getVillage().setCommande(null);
		//	---							Partie delegation
		//
		//	On verifie que le village appartient a la region demandee
		//
		int i;
		boolean appartientVillage = false;
		for(i = 0; i<r1.getVillages.size(); i++){
			if (m_caravanier.getVillage().equals(r.getVillages().get(i))){
				appartientVillage = true;
				break;
			}
		}
		
		appartientVillage = false;
		for(i = 0; i<r2.getVillages.size(); i++){
			if (m_caravanier.getVillage().equals(r.getVillages().get(i))){
				appartientVillage = true;
				break;
			}
		}
		//	On verifie que le nombre de delegations restantes est suffisant
		//
		if(appartientVillage == true){
			if (m_caravanier.nbDelegationsRestantes < 2) return false;
		}
		else return false;
		//	On envoie les delegations dans les regions saouhaitees et on les retire au caravanier
		//
		int nbDeleg = r.getNbDelegation(m_caravanier.couleur), nbDelegCarav = m_caravanier.getNbDelegationsRestantes();
		r.getNbDelegation.remove(m_caravanier.couleur);
		r.getNbDelegation.put(m_caravanier.couleur,nbDeleg+1);
		m_caravanier.setNbDelegationsRestantes(nbDelegCarav-1);
		nbDelegCarav = m_caravanier.getNbDelegationsRestantes();
		r2.getNbDelegation.remove(m_caravanier.couleur);
		r2.getNbDelegation.put(m_caravanier.couleur,nbDeleg+1);
		m_caravanier.setNbDelegationsRestantes(nbDelegCarav-1);
		return true;
		
	}

	//	---		Methode delegationTroc avec 3 regions
	//
	/**
	 * Pose un stupa et envoie des delegations dans les regions passees en parametre
	 * @param r1
	 * @param r2
	 * @param r3
	 * @return true si tout se passe bien, false si le nombre delegations est insuffisant ou si le village
	 * n'est pas adjacent a la region
	 */
	public boolean delegationTroc(Region r1, Region r2, Region r3){
		//		Honorer la commande
		//
		honorerCommande();
		//	Partie troc
		//
		//		On ajoute la valeur de la commande au pouvoir economique du caravanier
		int ancienPouvoirEco = m_caravanier.getPouvoirEconomique();
		m_caravanier.setPouvoirEconomique(ancienPouvoirEco + m_caravanier.getPosition().getCommande().getValeurCommande());
		//	On ajoute la commande a la banque et on la retire au village
		//
		Himalaya.getBanque().sacCommandes.put(m_caravanier.getVillage().getCommande());
		m_caravanier.getVillage().setCommande(null);
		//	---							Partie delegation
		//
		//	On verifie que le village appartient a la region demandee
		//
		int i;
		boolean appartientVillage = false;
		for(i = 0; i<r1.getVillages.size(); i++){
			if (m_caravanier.getVillage().equals(r.getVillages().get(i))){
				appartientVillage = true;
				break;
			}
		}
		
		appartientVillage = false;
		for(i = 0; i<r2.getVillages.size(); i++){
			if (m_caravanier.getVillage().equals(r.getVillages().get(i))){
				appartientVillage = true;
				break;
			}
		}
		
		appartientVillage = false;
		for(i = 0; i<r3.getVillages.size(); i++){
			if (m_caravanier.getVillage().equals(r.getVillages().get(i))){
				appartientVillage = true;
				break;
			}
		}
		//	On verifie que le nombre de delegations restantes est suffisant
		//
		if(appartientVillage == true){
			if (m_caravanier.nbDelegationsRestantes < 3) return false;
		}
		else return false;
		//	On envoie les delegations dans les regions saouhaitees et on les retire au caravanier
		//
		int nbDeleg = r.getNbDelegation(m_caravanier.couleur), nbDelegCarav = m_caravanier.getNbDelegationsRestantes();
		r.getNbDelegation.remove(m_caravanier.couleur);
		r.getNbDelegation.put(m_caravanier.couleur,nbDeleg+1);
		m_caravanier.setNbDelegationsRestantes(nbDelegCarav-1);
		nbDelegCarav = m_caravanier.getNbDelegationsRestantes();
		r2.getNbDelegation.remove(m_caravanier.couleur);
		r2.getNbDelegation.put(m_caravanier.couleur,nbDeleg+1);
		m_caravanier.setNbDelegationsRestantes(nbDelegCarav-1);
		nbDelegCarav = m_caravanier.getNbDelegationsRestantes();
		r3.getNbDelegation.remove(m_caravanier.couleur);
		r3.getNbDelegation.put(m_caravanier.couleur,nbDeleg+1);
		m_caravanier.setNbDelegationsRestantes(nbDelegCarav-1);
		return true;
		
	}
	//	---							Methode prendreSentier
	//
	//	Cette methode deplace le caravanier d'un village de depart a un village d'arrivee
	//
	/**
	 * Cette methode deplace le caravanier d'un village de depart a un village d'arrivee
	 * @param typeSentier
	 */
	public void prendreSentier(){
		Village villageActuel = m_caravanier.position;
		Village villageArrivee;
		
		//	On parcourt la ligne du village de depart dans la matrice des sentiers a la recherche
		//	du bon type de sentier afin d'en deduire le village d'arrivee
		//
		int i;
		for(i=0; i< Plateau.sentiers.length; i++){
			if (m_typeAction == Plateau.sentiers[villageActuel.numero][i].type){
				villageArrivee = Plateau.sentiers[villageActuel.numero][i].villageArrivee;
				break;
			}
		}
		//	On etablit le nouveau village du caravanier
		//
		m_caravanier.setPosition(villageArrivee);
	}
	
	//	---							Methode ne rien faire
	//
	/**
	 * Cette methode ne fait rien, elle permet au jouer de passer son tour
	 */
	public void rienFaire(){
	}
	
}
